.. role:: raw-html-m2r(raw) :format: html .. _utils: Utils ===== General ------- Many tools and utilities are present in :ref:`spinal.lib ` but some are already present in the SpinalHDL Core. .. list-table:: :header-rows: 1 :widths: 3 1 4 * - Syntax - Return - Description * - ``widthOf(x : BitVector)`` - Int - Return the width of a Bits/UInt/SInt signal * - ``log2Up(x : BigInt)`` - Int - Return the number of bits needed to represent ``x`` states * - ``isPow2(x : BigInt)`` - Boolean - Return true if ``x`` is a power of two * - ``roundUp(that : BigInt, by : BigInt)`` - BigInt - Return the first ``by`` multiply from ``that`` (included) * - ``Cat(x : Data*)`` - Bits - Concatenate all arguments, the first in MSB, the last in LSB Cloning hardware datatypes -------------------------- You can clone a given hardware data type by using the ``cloneOf(x)`` function. It will return a new instance of the same Scala type and parameters. For example: .. code-block:: scala def plusOne(value : UInt) : UInt = { // Will recreate a UInt with the same width than ``value`` val temp = cloneOf(value) temp := value + 1 return temp } // treePlusOne will become a 8 bits value val treePlusOne = plusOne(U(3, 8 bits)) You can get more information about how hardware data types are managed on the :ref:`Hardware types page `. .. note:: If you use the ``cloneOf`` function on a ``Bundle``, this ``Bundle`` should be a ``case class`` or should override the clone function internally. Passing a datatype as construction parameter -------------------------------------------- Many pieces of reusable hardware need to be parameterized by some data type. For example if you want to define a FIFO or a shift register, you need a parameter to specify which kind of payload you want for the component. There are two similar ways to do this. The old way ^^^^^^^^^^^ A good example of the old way to do this is in this definition of a ``ShiftRegister`` component: .. code-block:: scala case class ShiftRegister[T <: Data](dataType: T, depth: Int) extends Component { val io = new Bundle { val input = in (cloneOf(dataType)) val output = out(cloneOf(dataType)) } // ... } And here is how you can instantiate the component: .. code-block:: scala val shiftReg = ShiftRegister(Bits(32 bits), depth = 8) As you can see, the raw hardware type is directly passed as a construction parameter. Then each time you want to create an new instance of that kind of hardware data type, you need to use the ``cloneOf(...)`` function. Doing things this way is not super safe as it's easy to forget to use ``cloneOf``. The safe way ^^^^^^^^^^^^ An example of the safe way to pass a data type parameter is as follows: .. code-block:: scala case class ShiftRegister[T <: Data](dataType: HardType[T], depth: Int) extends Component { val io = new Bundle { val input = in (dataType()) val output = out(dataType()) } // ... } And here is how you instantiate the component (exactly the same as before): .. code-block:: scala val shiftReg = ShiftRegister(Bits(32 bits), depth = 8) Notice how the example above uses a ``HardType`` wrapper around the raw data type ``T``, which is a "blueprint" definition of a hardware data type. This way of doing things is easier to use than the "old way", because to create a new instance of the hardware data type you only need to call the ``apply`` function of that ``HardType`` (or in other words, just add parentheses after the parameter). Additionally, this mechanism is completely transparent from the point of view of the user, as a hardware data type can be implicitly converted into a ``HardType``. Frequency and time ------------------ SpinalHDL has a dedicated syntax to define frequency and time values: .. code-block:: scala val frequency = 100 MHz val timeoutLimit = 3 ms val period = 100 us val periodCycles = frequency * period val timeoutCycles = frequency * timeoutLimit | For time definitions you can use following postfixes to get a ``TimeNumber``: | ``fs``, ``ps``, ``ns``, ``us``, ``ms``, ``sec``, ``mn``, ``hr`` | For time definitions you can use following postfixes to get a ``HertzNumber``: | ``Hz``, ``KHz``, ``MHz``, ``GHz``, ``THz`` ``TimeNumber`` and ``HertzNumber`` are based on the ``PhysicalNumber`` class which use scala ``BigDecimal`` to store numbers. Binary prefix ------------- SpinalHDL allows the definition of integer numbers using binary prefix notation according to IEC. .. code-block:: scala val memSize = 512 MiB val dpRamSize = 4 KiB The following binary prefix notations are available: .. list-table:: :header-rows: 1 :widths: 1 2 * - Binary Prefix - Value * - Byte, Bytes - 1 * - KiB - 1024 == 1 << 10 * - MiB - 1024\ :sup:`2` == 1 << 20 * - GiB - 1024\ :sup:`3` == 1 << 30 * - TiB - 1024\ :sup:`4` == 1 << 40 * - PiB - 1024\ :sup:`5` == 1 << 50 * - EiB - 1024\ :sup:`6` == 1 << 60 * - ZiB - 1024\ :sup:`7` == 1 << 70 * - YiB - 1024\ :sup:`8` == 1 << 80